package com.tjetc;

import org.apache.ibatis.session.SqlSession;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;

/**
 * mapper接口的代理对象
 *
 * @author gaoyongxiang
 * @version v1.0
 * @date 2025/8/20
 */
public class MyMapperProxy implements InvocationHandler {

    private MySqlSession sqlSession;
    private String mapperFile;
    private MyConfiguration myConfiguration;

    // 简化了mapper文件的查找
    public MyMapperProxy(MySqlSession mySqlSession, Class clazz, MyConfiguration myConfiguration) {
        this.sqlSession = mySqlSession;
        this.mapperFile = clazz.getSimpleName() + ".xml";
        this.myConfiguration = myConfiguration;
    }

    /**
     * 当执行到代理对象时 就会执行invoke方法
     *
     * @param proxy  要代理的对象
     * @param method 要执行的方法是什么 selectBankById 在xml 只有这一个方法么？
     * @param args   执行方法的参数
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 根据mapper的xml文件 拿到MapperBean对象
        MapperBean mapperBean = myConfiguration.readMapper(mapperFile);

        // 判断是否是该接口的xml文件
        // 如果你要执行的方法不是该方法对应的那个xml文件 不正确
        if (!Objects.equals(method.getDeclaringClass().getName(), mapperBean.getInterfaceName())) {
            return null;
        }

        // 找到你要找到要执行的method对应的接口方法信息

        List<Function> functionList = mapperBean.getFunctionList();
        for (Function function : functionList) {
            // 开始比对方法
            if (Objects.equals(method.getName(), function.getFunctionName())) {
                // 即使方法名相同，但是具体要执行的方法还不清楚
                // 比如：selectBankById 一定执行的是select么？
                // 简化操作
                // 1.省略判断其他类型的方法
                // 2.省略处理参数解析，sql怎么拼接的，返回类型怎么处理的
                if ("select".equalsIgnoreCase(function.getSqlType())) {
                    // 就要执行对应该方法的sql语句
                    return sqlSession.selectOne(function.getSql(), args[0]);
                }

            }
        }

        return null;
    }
}